package owg.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;


public class NativeLibraryUtil
	{
	public final static String OS_NAME = System.getProperty("os.name").toLowerCase();
	public final static String JVM_BITS = System.getProperty("sun.arch.data.model");
	
	public final static String OS_ARCH_PATH;
	public final static String LIBRARY_EXTENSION;
	
	static
		{
		if(isWindows())
			{
			LIBRARY_EXTENSION = ".dll";
			if(is64Bit())
				OS_ARCH_PATH = "windows-x64";
			else
				OS_ARCH_PATH = "windows-x86";
			}
		else if(isUnix())
				{
				LIBRARY_EXTENSION = ".dll";
				if(is64Bit())
					OS_ARCH_PATH = "linux-x64";
				else
					OS_ARCH_PATH = "linux-x86";
				}
		else
			throw new RuntimeException("OS not supported... "+OS_NAME);
		}

	/**Copies a native library from a jar file on the classpath to the specified directory.<br>
	 * The argument should be the file name, with no directories and no file extension.<br>
	 * The library files should be stored in the directory corresponding to the OS and architecture, e.g. windows-x86 and linux-x64 etc.<br>
	 * The native library for the current OS and JVM architecture will be extracted to the indicated folder, and deleted upon JVM shutdown.*/
	public static void extractLibraryFromJar(String libraryPrefix, String directory)
		{
		try
			{
			File output = new File(directory, libraryPrefix+LIBRARY_EXTENSION);
			output.createNewFile();
			output.deleteOnExit();
			extractLibraryFromJar(libraryPrefix, output);
			}
		catch (IOException e)
			{
			e.printStackTrace();
			}
		}
	
	/**Copies a native library from a jar file on the classpath to the specified file.<br>
	 * The argument should be the file name, with no directories and no file extension.<br>
	 * The library files should be stored in the directory corresponding to the OS and architecture, e.g. windows-x86 and linux-x64 etc.<br>
	 * The native library for the current OS and JVM architecture will be extracted to the indicated file.*/
	private static void extractLibraryFromJar(String libraryPrefix, File output)
		{
		String dirName = OS_ARCH_PATH;
		String prefix = libraryPrefix;
		String suffix = LIBRARY_EXTENSION;
		
		InputStream in = null;
		FileOutputStream out = null;
		
		try
			{
			String src = dirName+'/'+prefix+suffix;
			System.out.println("Copying "+libraryPrefix+" libs from: "+src+" to tmp file: "+output.getAbsolutePath());
			
			in = ClassLoader.getSystemClassLoader().getResourceAsStream(src);
			if(in == null)
				throw new IOException(src+" is missing from classpath!");
			
			out = new FileOutputStream(output);
			
			byte[] buf = new byte[8192];
			int read;
			while((read = in.read(buf)) > 0)
				{
				out.write(buf, 0, read);
				}
			in.close();
			in = null;
			
			out.close();
			out = null;
			}
		catch (IOException e)
			{
			e.printStackTrace();
			}
		catch (UnsatisfiedLinkError e)
			{
			e.printStackTrace();
			}
		finally
			{
			if(in!=null)try{in.close();}catch(Exception e){}
			if(out!=null)try{out.close();}catch(Exception e){}
			}
		}
	
	/**Attempts to load a native library from a jar file on the classpath.<br>
	 * The argument should be the file name, with no directories and no file extension.<br>
	 * The library files should be stored in the directory corresponding to the OS and architecture, e.g. windows-x86 and linux-x64 etc.<br>
	 * The native library for the current OS and JVM architecture will be extracted to a temporary folder, loaded into the JVM, and deleted upon JVM shutdown.*/
	public static void loadLibraryFromJar(String libraryPrefix)
		{
		try
			{
			File tmp = File.createTempFile(libraryPrefix, LIBRARY_EXTENSION);
			tmp.deleteOnExit();
			extractLibraryFromJar(libraryPrefix, tmp);
			System.load(tmp.getAbsolutePath());
			}
		catch (IOException e)
			{
			e.printStackTrace();
			}
		catch (UnsatisfiedLinkError e)
			{
			e.printStackTrace();
			}
		}
	
	public static boolean is64Bit()
		{
		return (JVM_BITS.indexOf("64") >= 0);
		}

	public static boolean isWindows() 
		{
		return (OS_NAME.indexOf("win") >= 0);
		}

	public static boolean isMac() 
		{
		return (OS_NAME.indexOf("mac") >= 0);
		}

	public static boolean isUnix() 
		{
		return (OS_NAME.indexOf("nix") >= 0 || OS_NAME.indexOf("nux") >= 0 || OS_NAME.indexOf("aix") > 0 );
		}

	public static boolean isSolaris() 
		{
		return (OS_NAME.indexOf("sunos") >= 0);
		}
	}
